import os
import numpy as np
import functools
from pathlib import Path
import json
import configparser
import cv2
import gdcm
from PyQt5 import QtWidgets
from PyQt5 import QtCore
from PyQt5 import QtGui
from PyQt5.QtCore import Qt
from ui_report import Ui_MainWindow, Ui_ResultWindow
from reports import parse_case_xml
from utils.qt import addActions, settingAction, newIcon, settingButton, RightMenu
from dcm import read_dcm_info, convert_pixel_to_ct, convert_dcm_grayscale8, scipy_resize, read_dcm_to_8bit
from itk_snap import open_itksnape
from mmdetect import mmDetector
from mmdet.ops import nms
__appname__ = "ReportMG"
__notefile__ = ".gdReport"
__version__ = "0.2.0"


class WindowMixin(object):
    def menu(self, title, actions=None):
        menu = self.menuBar().addMenu(title)
        if actions:
            addActions(menu, actions)
        return menu


class AIResultWindow(QtWidgets.QWidget, Ui_ResultWindow):
    """
    显示结果窗口AIWindows;
    控制显示图像的顺序大小等;
    """
    def __init__(self):
        super(AIResultWindow, self).__init__()
        self.setupUi(self)
        self.setWindowTitle('AI筛查结果')
        self.graphViewSize = (512, 512)
        self.showDicomViewDict = {}

    def showMGDcm(self, detect_result):
        for i, dcm_image in enumerate(detect_result):
            dcm_image = scipy_resize(dcm_image, self.graphViewSize)
            height, width, channel = dcm_image.shape   #
            image = QtGui.QImage(dcm_image.data, width, height, QtGui.QImage.Format_RGB888)
            piximage = QtGui.QPixmap.fromImage(image)
            fitpiximage = piximage.scaled(height, height, QtCore.Qt.IgnoreAspectRatio, QtCore.Qt.SmoothTransformation)
            icon = QtGui.QIcon(fitpiximage)
            icon_size = QtCore.QSize(height, height)

            if i == 0:
                self.R_CC_View.setIcon(icon)
                self.R_CC_View.setIconSize(icon_size)
                # self.showDicomViewDict[self.R_CC_View.objectName()] = dcm_info['dcm_file']
            elif i == 1:
                self.L_CC_View.setIcon(icon)
                self.L_CC_View.setIconSize(icon_size)
                # self.showDicomViewDict[self.L_CC_View.objectName()] = dcm_info['dcm_file']

            elif i == 2:
                self.R_MLO_View.setIcon(icon)
                self.R_MLO_View.setIconSize(icon_size)
                # self.showDicomViewDict[self.R_MLO_View.objectName()] = dcm_info['dcm_file']

            elif i == 3:
                self.L_MLO_View.setIcon(icon)
                self.L_MLO_View.setIconSize(icon_size)
                # self.showDicomViewDict[self.L_MLO_View.objectName()] = dcm_info['dcm_file']


class ReportMainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, window_name:str=None, config:dict=None):
        # initial window
        super(ReportMainWindow, self).__init__()
        self.setupUi(self)
        self.setWindowTitle(window_name)

        self.dirty = False
        self.refresh_label_item = False
        self.maxRecent = 7

        self.graphViewSize = (256, 256)

        self.lastOpenDir = None
        self.curCaseDirName = None
        self.recentDires = []
        self.showDicomViewDict={}
        self.label_item_dict = {}
        self.mg_dcms = {}
        config_file = './mmData/cascade_rcnn_dconv_c3-c5_r50_fpn_1x_CBIS.py'
        self.mmDetector = mmDetector(config_file, show=True)

        self.itk_snap_app = config['dicom_app']
        if not os.path.exists(self.itk_snap_app):
            choice = QtWidgets.QMessageBox.critical(self, 'itksnap', 'itksnap 不存在！',
                                                    QtWidgets.QMessageBox.Ok)
            return

        # Restore app setting
        self.settings = QtCore.QSettings("GD", "reportMG")

        self.recentDires = self.settings.value('recentDires', []) or []
        size = self.settings.value('window/size', QtCore.QSize(600, 500))
        position = self.settings.value('window/position', QtCore.QPoint(0, 0))
        self.resize(size)
        self.move(position)
        self.restoreState(self.settings.value('window/state', QtCore.QByteArray()))

        self.R_CC_View.setFixedSize(QtCore.QSize(self.graphViewSize[0], self.graphViewSize[1]))
        self.L_CC_View.setFixedSize(QtCore.QSize(self.graphViewSize[0], self.graphViewSize[1]))
        self.R_MLO_View.setFixedSize(QtCore.QSize(self.graphViewSize[0], self.graphViewSize[1]))
        self.L_MLO_View.setFixedSize(QtCore.QSize(self.graphViewSize[0], self.graphViewSize[1]))

        self.saveLableButton.setFixedSize(QtCore.QSize(256, 128))
        self.AIdetectButton.setFixedSize(QtCore.QSize(256, 128))
        self.tool_opend_dir.setFixedSize(QtCore.QSize(128, 64))
        self.tool_prev_case.setFixedSize(QtCore.QSize(128, 64))
        self.tool_next_case.setFixedSize(QtCore.QSize(128, 64))

        settingAction(self.open_dir, slot=self.openDirDialog, shortcut=None, icon=None, tip=u'打开文件夹')
        settingAction(self.quit, slot=self.close, shortcut=None, icon=None, tip=u'退出程序')

        settingButton(self.tool_opend_dir, icon='open', slot=self.openDirDialog)
        settingButton(self.tool_next_case, icon='next', slot=self.openNextCase)
        settingButton(self.tool_prev_case, icon='prev', slot=self.openPrevCase)

        settingButton(self.R_CC_View, icon=None, slot=self.editDicomView)
        settingButton(self.L_CC_View, icon=None, slot=self.editDicomView)
        settingButton(self.L_MLO_View, icon=None, slot=self.editDicomView)
        settingButton(self.L_MLO_View, icon=None, slot=self.editDicomView)
        settingButton(self.saveLableButton, icon=None, slot=self.saveEidtLabel)
        settingButton(self.AIdetectButton, icon=None, slot=self.AIdetect)

        self.Right_PosComboBox.currentIndexChanged.connect(self.setDirty)
        self.Right_NegComboBox.currentIndexChanged.connect(self.setDirty)
        self.Right_BIRadsComboBox.currentIndexChanged.connect(self.setDirty)
        self.Left_PosComboBox.currentIndexChanged.connect(self.setDirty)
        self.Left_NegComboBox.currentIndexChanged.connect(self.setDirty)
        self.Left_BIRadsComboBox.currentIndexChanged.connect(self.setDirty)

        self.fileListWidget.itemSelectionChanged.connect(self.fileSelectionChanged)

        self.saveLabelItems()
        # self.updateFileMenu()
    # ======================================================================= #
        self.mmDetector.init()
        self.AIwindow = AIResultWindow()
    # ======================================================================= #

    def AIdetect(self):
        """
        根据读取的图像showDicomViewDict按照R_CC,L_CC,R_MOL,L_MLO进行排列得到 image_items;
        mmDetector对列表进行筛查并返回筛查结果图序列  detect_result
        # 对结果进行非极大值抑制及 阈值处理  #
        AIWindows显示结果;
        """
        if len(self.mg_dcms) <= 0:
            choice = QtWidgets.QMessageBox.question(self, 'File_load', '是否重新选择文件路径?',
                                                    QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.Cancel)
            if choice == QtWidgets.QMessageBox.Yes:
                self.quit
            elif choice == QtWidgets.QMessageBox.Cancel:
                self.quit
        else:
            # with open('detect_result.json', 'r') as load_file:  # patch序列
            #     detect_result = json.load(load_file)
            image_items = []
            image_list = list(self.showDicomViewDict.values())
            for i in range(len(image_list)):
                image_part = self.mg_dcms[i]['body_part'].split(' ')[0]+'_'+ self.mg_dcms[i]['PatientOrientation']
                if 'Right_CC' in image_part:
                    image_items.append(image_list[i])
            for i in range(len(image_list)):
                image_part = self.mg_dcms[i]['body_part'].split(' ')[0] + '_' + self.mg_dcms[i]['PatientOrientation']
                if 'Left_CC' in image_part:
                    image_items.append(image_list[i])
            for i in range(len(image_list)):
                image_part = self.mg_dcms[i]['body_part'].split(' ')[0] + '_' + self.mg_dcms[i]['PatientOrientation']
                if 'Right_MLO' in image_part:
                    image_items.append(image_list[i])
            for i in range(len(image_list)):
                image_part = self.mg_dcms[i]['body_part'].split(' ')[0] + '_' + self.mg_dcms[i]['PatientOrientation']
                if 'Left_MLO' in image_part:
                    image_items.append(image_list[i])
            # image_items = list(self.showDicomViewDict.values())
            detect_result = self.mmDetector.infrence(image_items)

            # # 1. nms
            # # 2. threshold
            threshold = 0.5
            for i in range(len(detect_result)):
                for j in range(len(detect_result[i])):
                    detect_result[i][j], inds = nms(detect_result[i][j], iou_thr=0.7)
                    for k in range(len(detect_result[i][j])):
                        k = 0
                        prob = detect_result[i][j][k][4]
                        if prob < threshold:
                            detect_result[i][j] = np.delete(detect_result[i][j], 0, axis=0)
            self.AIwindow.showMGDcm(detect_result)
            self.AIwindow.show()
    # ======================================================================= #

    def editDicomView(self):
        """
        对dicom图像进行标注
        :return:
        """
        def exist_dcms(showDicomViewDict):
            flag = True
            for key, item in showDicomViewDict.items():
                if not os.path.exists(item):
                    flag = False
            return flag

        if len(self.showDicomViewDict) > 0:
            if exist_dcms(self.showDicomViewDict):
                sender = self.sender()
                click_button = sender.objectName()
                dcm_file = self.showDicomViewDict[click_button]
                self.opendItkSnap(dcm_file)

    def opendItkSnap(self,  dcm_file):
        choice = QtWidgets.QMessageBox.question(self, 'itksnap', '是否标注该影像?',
                                               QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.Cancel)
        if choice == QtWidgets.QMessageBox.Yes:
            dcm_view_param = [self.itk_snap_app, dcm_file]
            open_itksnape(dcm_view_param)
        elif choice == QtWidgets.QMessageBox.Cancel:
            return

    def fileSelectionChanged(self):
        items = self.fileListWidget.selectedItems()
        if not items:
            return
        item = items[0]
        if not self.mayContinue():
            return

        currIndex = self.caseDirList.index(str(item.text()))
        if currIndex < len(self.caseDirList):
            dirpath = self.caseDirList[currIndex]
            if dirpath:
                gdai_file_name = os.path.join(self.lastOpenDir,  __notefile__)
                config = configparser.ConfigParser()
                config["GDNote"] = {'lastDirName': dirpath}
                with open(gdai_file_name, 'w') as configfile:
                    config.write(configfile)
                lastDirName = dirpath
                self.loadCaseDirInfo(dirpath)

    def openDirDialog(self, _value=False, dirpath=None):
        if not self.mayContinue():
            return
        defaultOpenDirPath = dirpath if dirpath else "."
        if self.lastOpenDir and os.path.exists(str(self.lastOpenDir)):
            defaultOpenDirPath = self.lastOpenDir

        targetDirPath = str(QtWidgets.QFileDialog.getExistingDirectory(
            self, '%s - Open Directory' % __appname__, defaultOpenDirPath,
                  QtWidgets.QFileDialog.ShowDirsOnly |
                  QtWidgets.QFileDialog.DontResolveSymlinks))

        self.importDirCases(targetDirPath)

    def checkLastBrowseRecord(self, dirpath:str, scanDires:list=[], write_flag=False):
        # 加入判断是否有notefile 文件
        gdai_file_name = dirpath + os.sep + __notefile__;
        config = configparser.ConfigParser()
        lastDirName = ""
        if write_flag:
            config["GDNote"] = {'lastDirName': dirpath}
            with open(gdai_file_name, 'w') as configfile:
                config.write(configfile)
            lastDirName = dirpath
        else:
            if os.path.exists(gdai_file_name):
                # 读取上次最后查看过的文件
                config.read(gdai_file_name)
                hasLastFileName = config.has_section("GDNote")  # 配置组是否存在
                if hasLastFileName:
                    lastDirName = config['GDNote']['lastDirName']
                else:
                    config["GDNote"] = {'lastDirName': ''}
                    with open(gdai_file_name, 'w') as configfile:
                        config.write(configfile)
            elif len(scanDires) > 0:
                lastDirName = scanDires[0]
                config["GDNote"] = {'lastDirName': lastDirName}
                with open(gdai_file_name, 'w') as configfile:
                    config.write(configfile)
        return lastDirName

    def importDirCases(self, dirpath, pattern=None, load=True):
        """
        导入文件夹列表
        :param dirpath:输入目录
        :param pattern:
        :param load:
        :return:
        """
        if not self.mayContinue() or not dirpath:
            return

        self.lastOpenDir = dirpath
        self.fileListWidget.clear()

        scanDires = self.scanAllCaseDires(dirpath)
        if len(scanDires) <= 0:
            choice = QtWidgets.QMessageBox.question(self, 'File_load', '是否重新选择文件路径?',
                                                    QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.Cancel)
            if choice == QtWidgets.QMessageBox.Yes:
                self.quit
            elif choice == QtWidgets.QMessageBox.Cancel:
                self.quit
        for dirname in scanDires:
            if pattern and pattern not in dirname:
                continue
            label_file = os.path.join(dirname,  'report.json')
            item = QtWidgets.QListWidgetItem(dirname)
            item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
            if QtCore.QFile.exists(label_file):
                item.setCheckState(Qt.Checked)
            else:
                item.setCheckState(Qt.Unchecked)
            self.fileListWidget.addItem(item)

        lastDirName = self.checkLastBrowseRecord(dirpath, scanDires=scanDires)
        if (lastDirName in self.caseDirList):
            self.curCaseDirName = lastDirName
        self.openCurCaseDir(load=load)

    def scanAllCaseDires(self, parenetfolder:str):
        sub_dir_list=[]

        def get_case_dirs(folder):
            sub_dir_list.clear()
            for dir in os.listdir(folder):
                if os.path.isdir(os.path.join(folder, dir)):
                    sub_dir_list.append(os.path.join(folder, dir))
        temp_dirs = []
        for dir in os.listdir(parenetfolder):
            if os.path.isdir(os.path.join(parenetfolder, dir)):
                get_case_dirs(os.path.join(parenetfolder, dir))
                if len(sub_dir_list) == 2:
                    temp_dirs.append(os.path.join(parenetfolder, dir))
        return temp_dirs

    def openNextCase(self, _value=False):
        """
        打开下一个病例文件夹
        :return:
        """
        if not self.mayContinue():
            return
        caseDirList = self.caseDirList
        if len(caseDirList) <= 0:
            return

        self.refresh_label_item = True
        self.refreshLabel()
        self.refresh_label_item = False
        self.setClean()

        if self.curCaseDirName is None:
            caseName = caseDirList[0]
        else:
            curIndex = caseDirList.index(self.curCaseDirName)
            if curIndex + 1 < len(caseDirList):
                caseName = caseDirList[curIndex+1]
            else:
                caseName = caseDirList[-1]
        self.curCaseDirName = caseName
        if self.curCaseDirName:
            self.loadCaseDirInfo(self.curCaseDirName)

    def openPrevCase(self, _value=False):
        """
        打开上一个病例文件夹
        :return:
        """
        if not self.mayContinue():
            return
        caseDirList = self.caseDirList
        if len(caseDirList) <= 0:
            return
        if self.curCaseDirName is None:
            return

        self.refresh_label_item = True
        self.refreshLabel()
        self.refresh_label_item = False
        self.setClean()

        curIndex = caseDirList.index(self.curCaseDirName)
        if curIndex - 1 >= 0:
            caseName = caseDirList[curIndex - 1]
            if caseName:
                self.loadCaseDirInfo(caseName)

    def openCurCaseDir(self, _value=False, load:bool=True):
        """
        打开当前病例文件夹
        :return:
        """
        if not self.mayContinue():
            return

        caseDirList = self.caseDirList
        if len(caseDirList) <= 0:
            return

        if self.curCaseDirName is None:
            caseName = caseDirList[0]
        else:
            curIndex = caseDirList.index(self.curCaseDirName)
            if curIndex < len(caseDirList):
                caseName = caseDirList[curIndex]
            else:
                caseName = caseDirList[-1]
        self.curCaseDirName = caseName

        if self.curCaseDirName and load:
            self.loadCaseDirInfo(self.curCaseDirName)

    def loadCaseDirInfo(self, dirname=None):
        """
        导入当前文件夹，解析信息，进行显示
        :param dirname:
        :return:
        """
        caseDirList = self.caseDirList

        if dirname in caseDirList and self.fileListWidget.currentRow() != caseDirList.index(dirname):
            self.fileListWidget.setCurrentRow(caseDirList.index(dirname))
            self.fileListWidget.repaint()
            return

        if dirname is None:
            dirname = self.settings.value('curCaseDirName', '')
        dirname = str(dirname)
        if not QtCore.QDir(dirname).exists():
            self.errorMessage(
                'Error opening file', 'No such Dir: <b>%s</b>' % dirname)
            return False

        #解析文件夹信息
        medical_report = self.parase_case_dir(dirname)
        self.showMedicalReport(medical_report)

        #显示放射MG影像
        self.mg_dcms = self.readMGDcm(medical_report["FS_info"]["xml_name"])
        self.showMGDcm(self.mg_dcms)

        self.addRecentDir(dirname)

        self.status("Loaded %s" % os.path.basename(str(dirname)))

    def showMGDcm(self, mg_dcms):
        for i, dcm_info in enumerate(mg_dcms):
            icon = QtGui.QIcon()
            convert_pixel_to_ct(dcm_info)
            dcm_image = convert_dcm_grayscale8(dcm_info)

            dcm_image = scipy_resize(dcm_image, self.graphViewSize)

            height, width = dcm_image.shape
            byteValue = 1 * width
            image = QtGui.QImage(dcm_image.data, width, height, byteValue, QtGui.QImage.Format_Grayscale8)
            piximage = QtGui.QPixmap.fromImage(image)
            piximage = piximage.scaled(height, height)
            icon.addPixmap(piximage)

            icon_size = QtCore.QSize(self.graphViewSize[0], self.graphViewSize[1])

            if i == 0:
                self.R_CC_View.setIconSize(icon_size)
                self.R_CC_View.setFixedSize(icon_size)
                self.R_CC_View.setIcon(icon)
                self.showDicomViewDict[self.R_CC_View.objectName()] = dcm_info['dcm_file']
            elif i == 1:
                self.L_CC_View.setIconSize(icon_size)
                self.L_CC_View.setFixedSize(icon_size)
                self.L_CC_View.setIcon(icon)
                self.showDicomViewDict[self.L_CC_View.objectName()] = dcm_info['dcm_file']

            elif i == 2:
                self.R_MLO_View.setFixedSize(icon_size)
                self.R_MLO_View.setIconSize(icon_size)
                self.R_MLO_View.setIcon(icon)
                self.showDicomViewDict[self.R_MLO_View.objectName()] = dcm_info['dcm_file']

            elif i == 3:
                self.L_MLO_View.setIconSize(icon_size)
                self.L_MLO_View.setFixedSize(icon_size)
                self.L_MLO_View.setIcon(icon)
                self.showDicomViewDict[self.L_MLO_View.objectName()] = dcm_info['dcm_file']

            # if dcm_info["PatientOrientation"] == "MLO":
            #     self.R_CC_View.setScene(scene)
            # elif dcm_info["PatientOrientation"] == "LC":
            #     self.L_CC_View.setScene(scene)
            # elif dcm_info["PatientOrientation"] == "RMLO":
            #     self.R_MLO_View.setScene(scene)
            # elif dcm_info["PatientOrientation"] == "LMLO":
            #     self.L_MLO_View.setScene(scene)

    def readMGDcm(self, xml_file):
        xml_file = Path(xml_file)
        root_dir = xml_file.parent

        dcm_info_list = []
        dcm_files = root_dir.glob("*.dcm")
        for file in dcm_files:
            dcm_info_list.append(read_dcm_info(str(file)))
        return dcm_info_list

    def load_fake_report(self):
        from reports import read_fake_json
        return read_fake_json()

    def parase_case_bl_or_fs_dir(self, dirname):
        """
        解析搜索xml文件，解析xml
        :param dirname:
        :return:
        """
        diagnosis_xml = list(Path(dirname).glob("diagnosis.*"))[0]
        diagnosis_dict = parse_case_xml(str(diagnosis_xml))
        return diagnosis_dict

    def parase_case_dir(self, dirname):
        """
        解析病例下两个子文件夹的xml信息
        :param dirname:
        :return:
        """
        if not os.path.isdir(dirname):
            return None
        sub_dir_list = []

        def get_case_dirs(folder):
            sub_dir_list.clear()
            for dir in os.listdir(folder):
                if os.path.isdir(os.path.join(folder, dir)):
                    sub_dir_list.append(os.path.join(folder, dir))

        get_case_dirs(dirname)
        report = {}
        if len(sub_dir_list) == 2:
            for sub_dir in sub_dir_list:
                parse_dict = self.parase_case_bl_or_fs_dir(sub_dir)
                if parse_dict["modality"] == "2":
                    report["FS_info"] = parse_dict
                elif parse_dict["modality"] == "3":
                    report["BL_info"] = parse_dict

        return report

    def loadRecent(self, dirname):
        if self.mayContinue():
            self.loadCaseDirInfo(dirname)

    def status(self, message, delay=5000):
        self.statusBar().showMessage(message, delay)

    @property
    def caseDirList(self):
        lst = []
        for i in range(self.fileListWidget.count()):
            item = self.fileListWidget.item(i)
            lst.append(item.text())
        return lst

    def mayContinue(self):
        """
        判断当前窗口是否存在未完成的任务.
        :return:
        """
        if not self.dirty:
            return True
        mb = QtWidgets.QMessageBox
        msg = 'Save annotations to "{}" before closing?'.format(self.curCaseDirName)
        answer = mb.question(self,
                             'Save annotations?',
                             msg,
                             mb.Save | mb.Discard | mb.Cancel,
                             mb.Save)
        if answer == mb.Discard:
            return True
        elif answer == mb.Save:
            self.saveEidtLabel()
            return True
        else:  # answer == mb.Cancel
            return False

    def addRecentDir(self, dirname):
        if dirname in self.recentDires:
            self.recentDires.remove(dirname)
        elif len(self.recentDires) >= self.maxRecent:
            self.recentDires.pop()
        self.recentDires.insert(0, dirname)

    def updateFileMenu(self):
        current = self.curCaseDirName

        def exists(filename):
            return os.path.exists(str(filename))

        menu = self.menu.open_recent_dir
        menu.clear()
        dires = [f for f in self.recentDires if f != current and exists(f)]
        for i, f in enumerate(dires):
            icon = newIcon('labels')
            action = QtWidgets.QAction(
                icon, '&%d %s' % (i + 1, QtCore.QFileInfo(f).fileName()), self)
            action.triggered.connect(functools.partial(self.loadRecent, f))
            menu.addAction(action)

    def closeEvent(self, event):
        if not self.mayContinue():
            event.ignore()
        self.settings.setValue(
            'curCaseDirName', self.curCaseDirName if self.curCaseDirName else '')
        self.settings.setValue('window/size', self.size())
        self.settings.setValue('window/position', self.pos())
        self.settings.setValue('window/state', self.saveState())
        self.settings.setValue('recentDires', self.recentDires)

    def showMedicalReport(self, report_dict):
        self.FSReport(report_dict)
        self.BLReport(report_dict)

    def FSReport(self, MedicalRecord):
        self.ExamPartlineEdit_FS.setText(MedicalRecord['FS_info']['body_of_case'])  # 检查部位
        self.AgelineEdit_FS.setText(str(MedicalRecord['FS_info']['age']))  # 年龄
        self.DescTextBrowser_FS.setText(MedicalRecord['FS_info']['desc_text'])  # 描述
        self.DiagnoseTextBrowser_FS.setText(MedicalRecord['FS_info']['diag_text'])  # 诊断

    def BLReport(self, MedicalRecord):
        self.ExamPartlineEdit_BL.setText(MedicalRecord['BL_info']['body_of_case'])  # 检查部位
        self.AgelineEdit_BL.setText(str(MedicalRecord['BL_info']['age']))  # 年龄
        self.DescTextBrowser_BL.setText(MedicalRecord['BL_info']['desc_text'])  # 描述
        self.DiagnoseTextBrowser_BL.setText(MedicalRecord['BL_info']['diag_text'])  # 诊断


    def refreshLabel(self):
        if self.label_item_dict:
            self.Right_PosComboBox.clear()
            self.Right_PosComboBox.addItems(self.label_item_dict["r_pos"])
            self.Right_PosComboBox.setCurrentIndex(1)
            self.Right_NegComboBox.clear()
            self.Right_NegComboBox.addItems(self.label_item_dict["r_neg"])
            self.Right_NegComboBox.setCurrentIndex(1)

            self.Left_PosComboBox.clear()
            self.Left_PosComboBox.addItems(self.label_item_dict["l_pos"])
            self.Left_PosComboBox.setCurrentIndex(1)
            self.Left_NegComboBox.clear()
            self.Left_NegComboBox.addItems(self.label_item_dict["l_neg"])
            self.Left_NegComboBox.setCurrentIndex(1)

            self.Right_BIRadsComboBox.clear()
            self.Right_BIRadsComboBox.addItems(self.label_item_dict["r_bi_rads"])
            self.Right_BIRadsComboBox.setCurrentIndex(0)
            self.Left_BIRadsComboBox.clear()
            self.Left_BIRadsComboBox.addItems(self.label_item_dict["l_bi_rads"])
            self.Left_BIRadsComboBox.setCurrentIndex(0)

    def saveLabelItems(self):
        self.label_item_dict["r_pos"] = [self.Right_PosComboBox.itemText(i) for i in range(self.Right_PosComboBox.count())]
        self.label_item_dict["r_neg"] = [self.Right_NegComboBox.itemText(i) for i in range(self.Right_NegComboBox.count())]
        self.label_item_dict["r_bi_rads"] = [self.Right_BIRadsComboBox.itemText(i) for i in range(self.Right_BIRadsComboBox.count())]
        self.label_item_dict["l_pos"] = [self.Left_PosComboBox.itemText(i) for i in range(self.Left_PosComboBox.count())]
        self.label_item_dict["l_neg"] = [self.Left_NegComboBox.itemText(i) for i in range(self.Left_NegComboBox.count())]
        self.label_item_dict["l_bi_rads"] = [self.Left_BIRadsComboBox.itemText(i) for i in range(self.Left_BIRadsComboBox.count())]


    def saveEidtLabel(self):
        """
        保存癌症标签标注信息
        :return:
        """
        if self.curCaseDirName and self.dirty:
            label_dict = {}
            label_dict["r_pos"] = self.Right_PosComboBox.currentText()
            label_dict["r_neg"] = self.Right_NegComboBox.currentText()
            label_dict["r_bi_rads"] = self.Right_BIRadsComboBox.currentText()
            label_dict["l_pos"] = self.Left_PosComboBox.currentText()
            label_dict["l_neg"] = self.Left_NegComboBox.currentText()
            label_dict["l_bi_rads"] = self.Left_BIRadsComboBox.currentText()
            save_file = os.path.join(self.curCaseDirName, 'report.json')
            with open(save_file, 'w', encoding="utf-8") as f:
                f.write(json.dumps(label_dict, ensure_ascii=False))

            items = self.fileListWidget.findItems(self.curCaseDirName, Qt.MatchExactly)
            if len(items) > 0:
                if len(items) != 1:
                    raise RuntimeError('There are duplicate files.')
                items[0].setCheckState(Qt.Checked)

            self.setClean()

    def setDirty(self):
        if self.curCaseDirName and not self.refresh_label_item:
            self.dirty = True
            title = __appname__
            if self.curCaseDirName is not None:
                title = '{} - {}*'.format(title, os.path.basename(self.curCaseDirName))
            self.setWindowTitle(title)

    def setClean(self):
        self.dirty = False
        title = __appname__
        if self.curCaseDirName is not None:
            title = '{} - {} - {}'.format(title, os.path.basename(self.curCaseDirName), self.curDirIndexStr)
        self.setWindowTitle(title)

    @property
    def curDirIndexStr(self):
        currIndex = self.caseDirList.index(self.curCaseDirName)
        return "{} / {}".format(currIndex, len(self.caseDirList))
